#define PIT_CTRL 0X0043
#define POT_CNT0 0x0040

#include "timer.h"


 TIMER_MANAGEMENT timer_man ; 


void init_pit (void ) { 
	int i ;
	TIMER * t ;
	io_out8(PIT_CTRL ,0x34) ;
	io_out8(POT_CNT0 ,0x9c) ;
	io_out8(POT_CNT0 ,0x2e) ;  // 0x2e9c表示一秒100次
	timer_man.count = 0 ;
	timer_man.next = 0xffffffff ; //最开始没有计数器
	for (i= 0 ; i< MAX_TIMER ;i ++) { 
		timer_man.timers0[i].flags = 0 ; //标记为未使用
	}  
	/**设置一个哨兵*/
	t = timer_alloc ();  
	t->timeout = 0xffffffff ;
	t->flags = TIMER_FLAGS_USING ;
	t->next = 0 ; 
	timer_man.t0 = t ;
	timer_man.next = t->timeout ;  
	return ;
}


TIMER * timer_alloc (void) { 
	int i ; 
	for (i = 0 ; i < MAX_TIMER ; i++) { 
		if (timer_man.timers0[i].flags == 0) { 
			timer_man.timers0[i].flags = TIMER_FLAGS_ALLOC ;
			return &timer_man.timers0[i] ;
		}
	}

	return 0 ; 
}

void timer_free( TIMER *timer)
{
	timer->flags = 0; 
	return;
}
void timer_init( TIMER *timer,CQUEUE * cq, char data )
{
	timer->cq = cq;
	timer->data.data = data;
	timer->data.code = INTDATA_CODE_TIMER ;
	timer->next = 0 ;
	return;
}
void timer_settime (TIMER * timer , unsigned int timeout ) {
	int eflags ; 
	TIMER * p,*q;
	timer->timeout =timer_man.count + timeout ;  
	timer->flags = TIMER_FLAGS_USING ;
	eflags = io_load_eflags();
	io_cli () ; //在操作timer_man时要禁止中断,否则造成数据冲突
	p = timer_man.t0 ;
	if (p->timeout > timer->timeout) { 
		timer_man.t0 = timer ; 
		timer_man.next = timer->timeout ; 
		timer->next = p ; 
		io_store_eflags(eflags);
		return  ;
	} 

	for (;;) {
		q = p ;
		p = p->next ;  
		if (p->timeout >= timer->timeout) { 
			 q->next = timer ; 
			 timer->next = p ; 
			 io_store_eflags(eflags);
			 return ; 
		}
	}
	
}

extern TIMER *task_timer ;  //multask.c
void handler_int20 (int * esp) {   //timer ，定时器中断
	TIMER *t ; 
	char flag = 0 ;  //任务切换标志
	io_out8(PIC0_OCW2,0x60) ; //表示IRQ1中断已受理 (0x60 + i) ,如果不执行这句，下次的IRQ0中断将被PIC忽略
	timer_man.count ++ ;
	if (timer_man.next > timer_man.count) { 
		return  ;
	}
	t = timer_man.t0 ; 
	for (;;) { 
		if (t->timeout > timer_man.count ){ 
			break ;
		}
		t->flags = TIMER_FLAGS_ALLOC;
		if (t ==task_timer) {
			flag = 1 ; 
		}else { 
			EnQueue(t->cq , t->data ) ; //timer的标记
		}
		t= t->next ;

	}
	timer_man.t0 = t  ;
	timer_man.next = t->timeout ;
	if (flag ==1) { 
		task_switch () ;
	}
	return ;
}


  